'use strict';

const pkgDir = require('pkg-dir').sync;
const fse = require('fs-extra');
const pathExists = require('path-exists').sync;
const npminstall = require('npminstall');
const path = require('path');

const {
    isObject
} = require('@dmj-cli/utils');
const {
    getDefaultRegistry,
    getNpmLatestVersion
} = require('@dmj-cli/get-npm-info');
const formatPath = require('@dmj-cli/format-path');
class Package {
    constructor(options) {
        if (!options) {
            throw new Error('Package类的options参数不能为空!');
        }
        if (!isObject(options)) {
            throw new Error('Package类的options参数必须为对象!');
        }
        this.targetPath = options.targetPath;
        // 缓存package的路径
        this.storeDir = options.storeDir;
        this.packageName = options.packageName;
        this.packageVersion = options.packageVersion;
        // 缓存目录前缀
        this.cacheFilePathPrefix = this.packageName.replace('/', '_');
    }

    async prepare() {
        // 解决缓存目录不存在问题
        if (this.storeDir && !pathExists(this.storeDir)) {
            // 这里会有个异步问题 使用promise版本的创建文件夹
            fse.mkdirpSync(this.storeDir)
        }
        // 拿到最新版本处理
        if (this.packageVersion === 'latest') {
            this.packageVersion = await getNpmLatestVersion(this.packageName);
        }
    }

    get cacheFilePath() {
        // 针对当前的npm模块
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`)
    }

    // 根据传入的版本去生成最新的路径
    getSpecificCacheFilePath(packageVersion) {
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`)
    }

    // 判断当前package是否存在
    async exists() {
        if (this.storeDir) {
            // 缓存模式
            await this.prepare()
            return pathExists(this.cacheFilePath);
        } else {
            return pathExists(this.targetPath);
        }
    }

    // 安装Package
    async install() {
        await this.prepare();
        return npminstall({
            root: this.targetPath,
            storeDir: this.storeDir,
            registry: getDefaultRegistry(),
            pkgs: [{
                name: this.packageName,
                version: this.packageVersion
            }]
        })
    }

    // 更新package
    async update() {
        await this.prepare();
        // 1、获取最新版本号
        const latestPackageVersion = await getNpmLatestVersion(this.packageName);
        // 2、查询最新版本号对应的路径是否存在
        const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion);
        // 3、如果不存在则直接安装最新版本
        if (!pathExists(latestFilePath)) {
            npminstall({
                root: this.targetPath,
                storeDir: this.storeDir,
                registry: getDefaultRegistry(),
                pkgs: [{
                    name: this.packageName,
                    version: latestPackageVersion
                }]
            });
            this.packageVersion = latestPackageVersion;
            console.log(this.packageVersion);
        }
        return latestFilePath;
    }

    // 获取入口文件的path
    getRootFilePath() {
        function _getRootFile(targetPath) {
            // 获取package.json中的所在目录 pkg-dir
            const dir = pkgDir(targetPath);
            if (dir) {
                // 读取package.json require()读取
                const pkgFile = require(path.resolve(dir, 'package.json'));
                if (pkgFile && pkgFile.main) {
                    // 路径的兼容(macos/windows) main/lib 输出成路径
                    return formatPath(path.resolve(dir, pkgFile.main));
                }
            }
            return null;
        }
        if (this.storeDir) {
            return _getRootFile(this.cacheFilePath);
        } else {
            return _getRootFile(this.targetPath);  
        }
    }
}

module.exports = Package;